package com.naiterui.ehp.bp.utils.lang;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.Validator;

import com.naiterui.ehp.bp.utils.context.SpringContextHolder;

/**
 * 验证工具类,基于JSR-303原生实现，支持注解如下 javax.validation.constraints.*
 *
 * @author wangzehao
 * @date 2018/10/18 2:29 PM
 * @since 1.0.0
 */
@SuppressWarnings({"WeakerAccess", "unused"})
public class ValidationUtils extends org.springframework.validation.ValidationUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(ValidationUtils.class);
    /**
     * 默认的验证类
     */
    private static final Validator VALIDATOR = SpringContextHolder.getBean(Validator.class);

    private ValidationUtils() {
    }

    /**
     * <pre>
     * 检查bean里标记为@Required的field是否为空，为空则抛异常
     * </pre>
     *
     * @param bean 要检查的bean对象
     *
     * @throws IllegalStateException 参数校验异常

     * @date 2017年09月09日
     * @since 1.0.0
     */
    public static void invokeValidatorError(Object bean) throws IllegalStateException {
        boolean invokeValidator = ValidationUtils.invokeValidator(bean);
        if (invokeValidator) {
            throw new IllegalStateException("参数校验错误错误");
        }
    }

    /**
     * 校验对象
     *
     * @param object
     *
     * @return 如果校验有错误，会返回true没有错误返回false
     */
    public static boolean invokeValidator(Object object) {
        Assert.notNull(object, "需要校验的对象不能为null");
        BeanPropertyBindingResult beanPropertyBindingResult = new BeanPropertyBindingResult(object, object.getClass().getName());
        ValidationUtils.invokeValidator(object, beanPropertyBindingResult);
        return beanPropertyBindingResult.hasErrors();
    }

    public static void invokeValidator(Object object, Errors errors, @Nullable Object... validationHints) {
        ValidationUtils.invokeValidator(VALIDATOR, object, errors, validationHints);
        if (errors.hasErrors()) {
            StringBuilder sb = new StringBuilder();
            errors.getAllErrors()
                  .stream()
                  .filter(allError -> allError instanceof FieldError)
                  .map(allError -> (FieldError) allError)
                  .forEach(fieldError -> {
                      String field = fieldError.getField();
                      String message = fieldError.getDefaultMessage();
                      sb.append(String.format("参数：%s 值：%s 错误信息:%s ", field, fieldError.getRejectedValue(), message));
                  });
            LOGGER.warn("校验失败 object:{} {}", object, sb);
        }
    }
}
